/* 
 * File:   CampaignList.cpp
 * Author: agu
 * 
 * Created on 16 de junio de 2014, 18:21
 */

#include "client_CampaignList.h"
#include <iostream>
#include <sstream>
#include <vector>
#define LARGO 5
using std::cout;
using std::endl;
using std::vector;
using std::stringstream;

CampaignList::CampaignList() :
vBox(Gtk::ORIENTATION_VERTICAL),
buttonBack("Volver"),
buttonRefresh("Actualizar") {

}

void CampaignList::connectWidgets() {
    //Conecto botones
    buttonBack.signal_clicked().connect(sigc::mem_fun(*this,
            &CampaignList::back));

    buttonRefresh.signal_clicked().connect(sigc::mem_fun(*this,
            &CampaignList::refresh));
    //Conecto lista
    treeView.signal_row_activated().connect(sigc::mem_fun(*this,
            &CampaignList::select));
    //Cerrar
    this->signal_hide().connect(sigc::mem_fun(this, &CampaignList::close));
    show_all_children();


}

CampaignList::~CampaignList() {
}

void CampaignList::setWindowsBack(Gtk::Window *windowBack) {
    this->windowsBack = windowBack;
}

void CampaignList::run() {
    this->loadWidgets();
    this->createModel();
    this->connectWidgets();
    this->show();
}

void CampaignList::close() {
    this->hide();
}

void CampaignList::back() {
    this->set_visible(false);
    this->windowsBack->set_visible(true);
}

void CampaignList::select(const Gtk::TreeModel::Path& path,
        Gtk::TreeViewColumn* /* column */) {
    Gtk::TreeModel::iterator iter = refTreeModel->get_iter(path);
    if (iter) {
        Gtk::TreeModel::Row row = *iter;
        //Aca deberia abrir una sala de espera para la partida en la que me quiero conectar        
        if (row[columns.m_col_status] == "En proceso") return;
        string namePlayer(this->entryName.get_chars(0, -1));        
        if (!namePlayer.empty()) {
            int id = row[columns.m_col_id];
            Glib::ustring name =row[columns.m_col_name];
            string msj = agregarLargo("U|" +std::to_string(id)+"|"+namePlayer);
            this->send(msj);
            msj= this->recv(); //recibo la letra que me referencia que color de jugador soy            
            this->watingRoom.setSocket(this->socket);
            this->watingRoom.setPlayerCode(msj);//debo recibirlo del server
            this->watingRoom.setGameName(name.c_str());
            this->watingRoom.setImagePath("VIENE POR MENSAJE");
            this->watingRoom.setWindowsBack(this);
            this->watingRoom.run();
            this->set_visible(false);
        }
    }
}

void CampaignList::refresh() {
    refTreeModel->clear();
    this->send("00002|M");
    gamesInfo.clear();
    this->getGamesInfo();
    Gtk::TreeModel::Row row;
    this->loadGamesInfo(row);
}

void CampaignList::loadWidgets() {
    set_title("Listado de partidas");
    set_border_width(5);
    set_default_size(600, 400);
    set_position(Gtk::WIN_POS_CENTER_ALWAYS);
    add(vBox);
    //Add the TreeView, inside a ScrolledWindow, with the button underneath:
    scrolledWindow.add(treeView);
    //Only show the scrollbars when they are necessary:
    scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
    vBox.pack_start(label);
    vBox.pack_start(entryName);
    vBox.pack_start(scrolledWindow);
    vBox.pack_start(buttonBox1, Gtk::PACK_SHRINK);
    vBox.pack_start(buttonBox2, Gtk::PACK_SHRINK);
    label.set_text("Nombre Jugador");
    buttonBox1.pack_start(buttonRefresh, Gtk::PACK_SHRINK);
    buttonBox1.set_border_width(5);
    buttonBox1.set_layout(Gtk::BUTTONBOX_CENTER);
    buttonBox2.pack_start(buttonBack, Gtk::PACK_SHRINK);
    buttonBox2.set_border_width(5);
    buttonBox2.set_layout(Gtk::BUTTONBOX_CENTER);
}

void CampaignList::setSocket(Client_socket s) {
    this->socket = s;
}

void CampaignList::createModel() {
    this->addColumns();
    this->send("00002|M");
    this->getGamesInfo();
    //Create the Tree model:
    refTreeModel = Gtk::ListStore::create(columns);
    treeView.set_model(refTreeModel);
    Gtk::TreeModel::Row row;
    refTreeModel->clear();
    this->loadGamesInfo(row);

}

void CampaignList::loadGamesInfo(Gtk::TreeModel::Row row) {
    for (unsigned int i = 0; i < gamesInfo.size(); i++) {
        row = *(refTreeModel->append());
        row[columns.m_col_id] = i;
        row[columns.m_col_name] = gamesInfo.at(i).at(0);
        row[columns.m_col_tot_play] = gamesInfo.at(i).at(1);
        row[columns.m_col_join_play] = gamesInfo.at(i).at(2);
        if (gamesInfo.at(i).at(1).compare(gamesInfo.at(i).at(2)) == 0) {
            row[columns.m_col_status] = "En proceso";
        } else {
            row[columns.m_col_status] = "En espera";
        }

    }
}

void CampaignList::addColumns() {
    //Add the TreeView's view columns:
    //This number will be shown with the default numeric formatting.
    treeView.append_column("Id", columns.m_col_id);
    treeView.append_column("Nombre Partida", columns.m_col_name);
    treeView.append_column("Total Jugadores", columns.m_col_tot_play);
    treeView.append_column("Jugadores Conectados", columns.m_col_join_play);
    treeView.append_column("Estado", columns.m_col_status);

}

void CampaignList::getGamesInfo() {
    string info = this->recv();    
    //Nombre|cantjugadores|cantrequerida
    vector<string> datos = this->getElementos(info, '|');
    vector<string> gameInfo;
    int x = 0;
    for (unsigned int i = 0; i < (datos.size() / 4); i++) {
        for (unsigned int j = 1; j < 4; j++) {
            gameInfo.push_back(datos.at(i * 3 + j + x));
        }
        x++;
        gamesInfo.push_back(gameInfo);
        gameInfo.clear();
    }
}

string CampaignList::recv() {
    string largoALeer;
    if (this->socket.recibir(&largoALeer, LARGO) == -1) {        
    }
    int largoInfo = stoi(largoALeer);
    string buffer;
    if (this->socket.recibir(&buffer, largoInfo) == -1) {        
    }
    buffer.erase(0, 1);
    return buffer;
}

void CampaignList::send(const string msj) {
    int tam = msj.size();
    this->socket.enviar(msj, tam);
}

vector<string> CampaignList::getElementos(const string& linea, char separador) {
    vector<string> elementos;
    stringstream ss(linea);
    string item;
    while (std::getline(ss, item, separador)) {
        elementos.push_back(item);
    }
    return elementos;
}

string CampaignList::agregarLargo(string buffer) {
    int largo = buffer.size() + 1;    
    char* formato = (char*) malloc((LARGO + 1) * sizeof (char));
    snprintf(formato, LARGO + 1, "%.5d", largo);
    string aux;
    aux.append(string(formato));
    aux.append("|");
    aux.append(buffer);
    free(formato);
    return aux;
}